#! /usr/bin/env python
# coding=utf-8
#======================================================================
# SecureGAppProxy is a security-strengthened version of GAppProxy.
# http://secure-gappproxy.googlecode.com                               
# This file is a part of SecureGAppProxy.                              
# Copyright (C) 2011  nleven <www.nleven.com i@nleven.com>             
#                                                                      
# This program is free software: you can redistribute it and/or modify 
# it under the terms of the GNU General Public License as published by 
# the Free Software Foundation, either version 3 of the License, or    
# (at your option) any later version.                                  
#                                                                      
# This program is distributed in the hope that it will be useful,      
# but WITHOUT ANY WARRANTY; without even the implied warranty of       
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        
# GNU General Public License for more details.                         
#                                                                      
# You should have received a copy of the GNU General Public License    
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#                                                                      
# ACKNOWLEDGEMENT                                                      
# SecureGAppProxy is a based on the work of GAppProxy                  
# <http://gappproxy.googlecode.com> by Du XiaoGang <dugang@188.com>
#======================================================================

import os, sys, re

def we_are_frozen():
    """Returns whether we are frozen via py2exe.
    This will affect how we find out where we are located."""

    return hasattr(sys, "frozen")

def module_path():
    """ This will get us the program's directory,
    even if we are frozen using py2exe"""

    if we_are_frozen():
        return os.path.dirname(sys.executable)
    return os.path.dirname(__file__)

dir = module_path()

VERSION = "0.31"
BUILD_NUM = 55

NETWORK_CHECKER = 'http://www.appspot.com/'

DEF_LISTEN_PORT = 8000
DEF_FETCH_PROTOCOL = 'http'
DEF_LOCAL_PROXY = ''
DEF_FETCH_SERVER = ''
DEF_REKEY_NAME = 'rekey'
DEF_CONF_FILE = os.path.join(dir, 'proxy.conf')
DEF_CERT_FILE = os.path.join(dir, 'cert_default/LocalProxyServer.cert')
DEF_KEY_FILE  = os.path.join(dir, 'cert_default/LocalProxyServer.key')
CERT_DIR = os.path.join(dir, 'cert_gen')

__conf_dict = None

def __parse_conf(confFile=DEF_CONF_FILE):
    global __conf_dict
    __conf_dict = {}
    # read config file
    try:
        fp = open(confFile, "r")
    except IOError:
        # use default parameters
        return
    # parse user defined parameters
    while True:
        line = fp.readline()
        if line == "":
            # end
            break
        # parse line
        line = line.strip()
        if line == "":
            # empty line
            continue
        if line.startswith("#"):
            # comments
            continue
        (name, sep, value) = line.partition("=")
        if sep == "=":
            name = name.strip().lower()
            value = value.strip()
            __conf_dict[name] = value
    fp.close()
    
def SaveConfig(conf_file=DEF_CONF_FILE):
    global __conf_dict
    try:
        fp = open(conf_file, 'w+')

        fp.write( '\n'.join( map(lambda s:'='.join(s),
                                 __conf_dict.items()
                                 )
                             )
                  )
    except IOError:
        return
    finally:
        fp.close()

    
    
def __port_validate(i, get):
    if get:
        ret = None
        try:
            ret = int(i)
            if ret <= 0 or ret >=65536:
                return False
        except:
            return False
    return True

def __proxytext_validate(proxy, get):
    return proxy == '' or re.match("(\\S+:\\S+@)?\\S+:\d+", proxy)

def __protocol_validate(protocol, get):
    return protocol.lower() in ['http', 'https']

def __bool_validate(b, get):
    if get:
        return b in ['0', '1']
    else:
        return b in [True, False]

def __bool_convertor(s, get):
    if get:
        return {'0':False, '1':True}[s]
    else:
        return {False:'0', True:'1'}[s]


def __int_convertor(s, get):
    if get:
        return int(s)
    else:
        return str(s)

def __base64_convertor(s, get):
    import base64
    if get:
        return base64.urlsafe_b64decode(s)
    else:
        return base64.urlsafe_b64encode(s)
    

__dont_validate = lambda x,y:True
__no_convertor = lambda x,y:x
__conf_default = { 'listen_port':       (DEF_LISTEN_PORT,       __port_validate,        __int_convertor),
                   'local_proxy':       ('',                    __proxytext_validate,   __no_convertor),
                   'fetch_server':      ('',                    __dont_validate,        __no_convertor),
                   'fetch_protocol':    (DEF_FETCH_PROTOCOL,    __protocol_validate,    __no_convertor),
                   'fetch_rekey':       (DEF_REKEY_NAME,        __dont_validate,        __no_convertor),
                   'password':          (None,                  __dont_validate,        __base64_convertor),
                   'auto_redirect':     (True,                  __bool_validate,        __bool_convertor),
                   }

def GetParam(key, default=None, validator=__dont_validate, convertor=__no_convertor):
    if not __conf_dict:
        __parse_conf(DEF_CONF_FILE)
    if key in __conf_default:
        default, validator, convertor = __conf_default[key]
        
    if key not in __conf_dict:
        return default
    else:
        val = __conf_dict[key]

    if not validator(val, True):
        return default
    else:
        return convertor(val, True)

def DeleteParam(key):
    if not __conf_dict:
        __parse_conf(DEF_CONF_FILE)
    __conf_default.pop(key, None)
        
def SetParam(key, value, validator=__dont_validate, convertor=__no_convertor):
    if not __conf_dict:
        __parse_conf(DEF_CONF_FILE)

    if key in __conf_default:
        default, validator, convertor = __conf_default[key]

    if validator(value, False):
        __conf_dict[key] = convertor(value, False)
    else:
        DeleteParam(key)






